// Copyright (c) 2020-present, INSPUR Co, Ltd. All rights reserved.
// This source code is licensed under Apache 2.0 License.
//
// Created by florian on 05.08.15.

#include "tree_node.h"
#include <algorithm>
#include <assert.h>

namespace syn_art_fullkey {

bool N48::insert(uint8_t key, N *n) {
  if (count_ == 48) {
    return false;
  }
  children_[count_].store(n, std::memory_order_release);
  childIndex_[key].store(count_, std::memory_order_release);
  count_++;
  return true;
}

void N48::change(uint8_t key, N *val) {
  uint8_t index = childIndex_[key].load();
  assert(index != emptyMarker);
  return children_[index].store(val, std::memory_order_release);
}

N *N48::getChild(const uint8_t k) const {
  uint8_t index = childIndex_[k].load();
  if (index == emptyMarker) {
    return nullptr;
  } else {
    return children_[index].load();
  }
}

void N48::getChildrenSmall(uint8_t start, uint8_t end,
                      std::tuple<uint8_t, N *> *&children48,
                      uint32_t &childrenCount, u_int32_t childMax) const {
  childrenCount = 0;
  for (unsigned i = start; i <= end; i++) {
    uint8_t index = this->childIndex_[i].load();
    if (index != emptyMarker) {
      N *child = this->children_[index].load();
      if (child != nullptr) {
        children48[childrenCount] = std::make_tuple(i, child);
        childrenCount++;
        if (childrenCount >= childMax)
          return;
      }
    }
  }
}
void N48::getChildrenLarge(uint8_t start, uint8_t end,
                      std::tuple<uint8_t, N *> *&children48,
                      uint32_t &childrenCount, u_int32_t childMax) const {
  childrenCount = 0;
  for (unsigned i = end; i >= start; --i) {
    uint8_t index = this->childIndex_[i].load();
    if (index != emptyMarker) {
      N *child = this->children_[index].load();
      if (child != nullptr) {
        children48[childMax - childrenCount - 1] = std::make_tuple(i, child);
        childrenCount++;
        if (childrenCount >= childMax)
          break;
      }
    }
  }
  if (childrenCount > 0 && childrenCount < childMax){
      memcpy(&(children48[0]), &(children48[childMax - childrenCount]), sizeof(std::tuple<uint8_t, N *>) * childrenCount);
  }
}
} // namespace syn_art_fullkey